﻿using System.Diagnostics.Metrics;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text.RegularExpressions;
using System.Threading;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting;
using OpenCvSharp;
using WampSharp.V2;
using WampSharp.V2.Realm;
using static System.Net.Mime.MediaTypeNames;

namespace WampAPI.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class CamController : ControllerBase
    {
        /// <summary>
        /// 取消用，并表示状态
        /// </summary>
        private static CancellationTokenSource _cancellationTokenSource = null;
        private static VideoCapture _capture = null;
        private static ISubject<byte[]> _subjectOpen = null;
        private static ISubject<string> _subjectClose = null;
        private static IWampHostedRealm _realm = null;
        private static Mat _image = new Mat();


        public CamController(WampHost host)
        {
            _capture ??= new VideoCapture();//下面再打开0
            _realm ??= host.RealmContainer.GetRealmByName("realm1");
            _subjectOpen ??= _realm.Services.GetSubject<byte[]>("opencam");
            _subjectClose ??= _realm.Services.GetSubject<string>("closecam");
        }

        [HttpGet("open")]
        public IActionResult Open()
        {
            if (_cancellationTokenSource != null && !_cancellationTokenSource.IsCancellationRequested)
            {
                return Ok("摄像头已打开，请勿重复操作");
            }

            if (_capture.Open(0))
            {
                _cancellationTokenSource = new CancellationTokenSource();
                PubCamOpen();

                return Ok("打开摄像头");
            }
            else
            {
                return Ok("打开摄像头失败");
            }

        }

        [HttpGet("close")]
        public IActionResult Close()
        {
            _cancellationTokenSource?.Cancel();
            _capture?.Release();
            PubCamClose();
            return Ok("关闭摄像头");
        }

        private async Task PubCamOpen()
        {
            IObservable<long> timer = Observable.Timer(TimeSpan.FromMilliseconds(0), TimeSpan.FromMilliseconds(30));

            timer.Subscribe(x =>
            {
                // 从摄像头读取一帧
                _capture?.Read(_image);

                // 如果读取到的帧为空，表示没有更多的帧可以读取
                if (_image.Empty())
                {
                    Console.WriteLine("No signal");
                    _cancellationTokenSource?.Cancel();
                    return;
                }
                Console.Write('.');
                try
                {
                    _subjectOpen.OnNext(_image.ToBytes());
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                    _subjectOpen.OnError(ex);
                    _cancellationTokenSource?.Cancel();
                    return;
                }

            }, _cancellationTokenSource.Token);


            // This line is required in order to release the WebSocket thread, otherwise it will be blocked by the following Console.ReadLine() line.
            await Task.Yield();
        }

        private async Task PubCamClose()
        {
            _subjectClose.OnNext("摄像头已关闭");
        }
    }
}
